package 多线程;

/**
 * 请实现N个线程，使之交替打印1-100*N
 *  思路：使用synchronized实现
 */
public class PrintNumbersAlternately {
    private static final Object lock = new Object(); // 定义对象锁
    private static int currentPrinter = 0; // 当前应该打印的线程编号 (0-based)
    private static int currentNumber = 1; // 当前要打印的数字
    private static final int N; // 线程数
    private static int MAX_NUMBER; // 最大的打印数字，由线程数决定

    static { // 初始化值
        N = 5;
        MAX_NUMBER = N * 100;
    }

    public static void main(String[] args) {
        Thread[] threads = new Thread[N];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new PrintNumber(i));
        }
        for (Thread thread : threads){
            thread.start();
        }

        // 等待所有的线程完成
        for (Thread thread : threads){
            try {
                thread.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    static class PrintNumber implements Runnable{

        private int idNumber; //当前线程的Id

        public PrintNumber(int idNumber){
            this.idNumber = idNumber;
        }

        @Override
        public void run() {
            // 当前遍历的值小于最大打印数字
            while (currentNumber <= MAX_NUMBER){
                // 获取锁对象
                synchronized (lock){
                    // 判断当前线程是否可以打印
                    while ( idNumber != currentPrinter && currentNumber <= MAX_NUMBER){
                        try {
                            // 等待
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    // 假如当前线程可以打印
                    if (currentNumber > MAX_NUMBER){ // 超出最大数字，循环停止
                        break;
                    }
                    System.out.println("PrintNumber"+ idNumber +"打印数字："+currentNumber);
                    currentNumber ++;
                    currentPrinter = (idNumber + 1) % N;
                    lock.notifyAll(); // 唤醒其余线程
                }
            }
        }
    }
}
